<?php
if (!defined('APP_ID')) { die('No direct script access allowed'); }

class Email_Driver_Smtp {
	const EOL = "\r\n";
	const EOD = '.';
	
	private $_parent = null;	
	private $_user = '';
	private $_password = '';
	private $_host = '';
	private $_port = 0;
	
	public function __construct($parent) {
		$this->_parent = $parent;
		$this->_user = Config::get('smtp_user', 'email', '');
		$this->_password = Config::get('smtp_password', 'email', '');
		$this->_host = Config::get('smtp_host', 'email', 'localhost');
		$this->_port = Config::get('smtp_port', 'email', 25);
	}
	
	public function send() {
		$result = false;

		$from = $this->_parent->getFrom(true);
		$to = $this->_parent->getTo(true);
		$cc = $this->_parent->getCc(true);
		$bcc = $this->_parent->getBcc(true);
		$headers = $this->_parent->getHeaders();
		$subject = $this->_parent->getSubject();
		$body = $this->_parent->getBody();

		try {
			$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
			if ($socket < 0) {
				throw new Exception('socket_create() failed: ' . socket_strerror(socket_last_error()));
			}

			$connected = socket_connect($socket, $this->_host, $this->_port);
			if ($connected === false) {
				throw new Exception('socket_connect() failed: ' . socket_strerror(socket_last_error()));
			}

			$this->_response($socket);

			$this->_request($socket, 'EHLO '.$this->_user);
			$this->_response($socket);

			$this->_request($socket, 'AUTH LOGIN');
			$this->_response($socket);

			$this->_request($socket, base64_encode($this->_user));
			$this->_response($socket);

			$this->_request($socket, base64_encode($this->_password));
			$this->_response($socket);

			foreach ($from as $item) {
				$this->_request($socket, 'MAIL FROM:<' . $item['email'] . '>');
				$this->_response($socket);
				break;
			}

			foreach ($to as $item) {
				$this->_request($socket, 'RCPT TO:<' . $item['email'] . '>');
				$this->_response($socket);
			}

			foreach ($cc as $item) {
				$this->_request($socket, 'RCPT TO:<' . $item['email'] . '>');
				$this->_response($socket);
			}

			foreach ($bcc as $item) {
				$this->_request($socket, 'RCPT TO:<' . $item['email'] . '>');
				$this->_response($socket);
			}

			$this->_request($socket, 'DATA');
			$this->_response($socket);

			if (!empty($headers)) {
				$this->_request($socket, $headers);
			}
			$this->_request($socket, 'Subject:' . $subject . self::EOL);
			$this->_request($socket, $body . self::EOL . self::EOD);
			$this->_response($socket);

			$this->_request($socket, 'QUIT');
			$this->_response($socket);

			$result = true;
		} catch (Exception $e) {}

		if (isset($socket)) {
			socket_close($socket);
		}

		return $result;
	}

	private function _response($socket) {
		$read = socket_read($socket, 1024);

		//echo $read, '<br />';

		if ($read{0} != '2' && $read{0} != '3') {
			if (!empty($read)) {
				throw new Exception('SMTP error: ' . $read);
			} else {
				throw new Exception('Unknown SMTP error');
			}
		}
	}

	private function _request($socket, $message) {
		$message .= self::EOL;
		socket_write($socket, $message, strlen($message));
	}
}